package FileIO;

import model.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.util.ArrayList;

public class PersistenciaLaberinto extends Persistible {

    private static PersistenciaLaberinto INSTANCE = null;

    private synchronized static void createInstance() {
        if (INSTANCE == null) {
            INSTANCE = new PersistenciaLaberinto();
        }
    }

    public static PersistenciaLaberinto getInstance() {
        createInstance();
        return INSTANCE;
    }

    @SuppressWarnings("CloneDoesntCallSuperClone")
    @Override
    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    private PersistenciaLaberinto() {

    }

    private void persistirNodo(DataNodo entornoElementoEscenario) {

        Document documentoXML = DocumentoXML.INSTANCE.getDocumentoXML();
        Element raiz = documentoXML.getDocumentElement();
        Element nodo = documentoXML.createElement(Constantes.NODO);

        nodo.setAttribute(Constantes.ID, entornoElementoEscenario.getId());
        nodo.setAttribute(Constantes.FILA, entornoElementoEscenario.getFila());
        nodo.setAttribute(Constantes.COLUMNA, entornoElementoEscenario.getColumna());
        nodo.setAttribute(Constantes.CONTIENE, entornoElementoEscenario.getContiene());
        nodo.setAttribute(Constantes.IZQUIERDA_LC, entornoElementoEscenario.getIzquierda());
        nodo.setAttribute(Constantes.DERECHA_LC, entornoElementoEscenario.getDerecha());
        nodo.setAttribute(Constantes.ARRIBA_LC, entornoElementoEscenario.getArriba());
        nodo.setAttribute(Constantes.ABAJO_LC, entornoElementoEscenario.getAbajo());

        raiz.appendChild(nodo);
    }

    public void persistir(Escenario escenario) {

        Document documentoXML = DocumentoXML.INSTANCE.getDocumentoXML();
        Element raiz = documentoXML.createElement(Constantes.LABERINTO);

        raiz.setAttribute(Constantes.ANCHO, getNumberWithCero(escenario.getY() - 2));
        raiz.setAttribute(Constantes.ALTO, getNumberWithCero(escenario.getX() - 2));
        raiz.setAttribute(Constantes.NODO_ANCHO, escenario.getNodoAncho());
        raiz.setAttribute(Constantes.NODO_ALTO, escenario.getNodoAlto());
        ElemEscenario posicionGuaridaFantasmas = escenario.getPosicionGuaridaFantasmas();
        ElemEscenario posicionInicialPacman = escenario.getPosicionInicialPacman();
        String posInicioPacman = getNumberWithCero(posicionInicialPacman.getY() - 1) + getNumberWithCero(posicionInicialPacman.getX() - 1);
        String posGuaridaFantasmas = getNumberWithCero(posicionGuaridaFantasmas.getY() - 1) + getNumberWithCero(posicionGuaridaFantasmas.getX() - 1);
        raiz.setAttribute(Constantes.INICIO_PACMAN, posInicioPacman);
        raiz.setAttribute(Constantes.INICIO_FANTASMAS, posGuaridaFantasmas);
        documentoXML.appendChild(raiz);

        persistirEscenario(escenario);

        escribirDocumentoEnArchivo(documentoXML, AppConfig.getInstance().getPathSalida() + Constantes.PREFIJO_LABERINTO_TICK + turnoArchivo() + Constantes.EXTENSION_XML);
        DocumentoXML.INSTANCE.limpiarDocumento();
    }

    private int turnoArchivo() {
        return Juego.getInstance().getTurno() + 1;
    }

    private void persistirEscenario(Escenario escenario) {

        ArrayList<ArrayList<ElemEscenario>> laberinto = escenario.getLaberinto();
        for (ArrayList<ElemEscenario> lista : laberinto) {
            for (ElemEscenario elemEscenario : lista) {
                Integer columna = elemEscenario.getX();
                Integer fila = elemEscenario.getY();

                if (fila == 0 || columna == 0 || fila == escenario.getY() - 1 || columna == escenario.getX() - 1)
                    continue;

                String id = getNumberWithCero(fila - 1) + getNumberWithCero(columna - 1);

                String izquierda = "";
                String derecha = "";
                String abajo = "";
                String arriba = "";
                String contiene = "";


                if (!elemEscenario.getClass().equals(Pared.class)) {

                    ElemEscenario posicionIzquierda = escenario.getPosicion(fila, columna - 1);
                    if (posicionIzquierda.isTransportable()) {
                        Transportador transportadorIzquierda = (Transportador) posicionIzquierda;
                        izquierda = getNumberWithCero(transportadorIzquierda.getyTransportador() - 1) + getNumberWithCero(transportadorIzquierda.getxTransportador() - 1);
                    } else {
                        izquierda = getNumberWithCero(posicionIzquierda.getY() - 1) + getNumberWithCero(posicionIzquierda.getX() - 1);
                        if (posicionIzquierda.getY() - 1 == -1 || posicionIzquierda.getX() - 1 == -1 || posicionIzquierda.getY() - 1 == escenario.getY() - 2 || posicionIzquierda.getX() - 1 == escenario.getX() - 2)
                            izquierda = "";
                    }

                    ElemEscenario posicionDerecha = escenario.getPosicion(fila, columna + 1);
                    if (posicionDerecha.isTransportable()) {
                        Transportador transportadorDerecha = (Transportador) posicionDerecha;
                        derecha = getNumberWithCero(transportadorDerecha.getyTransportador() - 1) + getNumberWithCero(transportadorDerecha.getxTransportador() - 1);
                    } else {
                        derecha = getNumberWithCero(posicionDerecha.getY() - 1) + getNumberWithCero(posicionDerecha.getX() - 1);
                        if (posicionDerecha.getY() - 1 == escenario.getY() - 3 || posicionDerecha.getX() - 1 == -1 || posicionDerecha.getY() - 1 == escenario.getY() - 2 || posicionDerecha.getX() - 1 == escenario.getX() - 2)
                            derecha = "";
                    }

                    ElemEscenario posicionAbajo = escenario.getPosicion(fila + 1, columna);
                    if (posicionAbajo.isTransportable()) {
                        Transportador transportadorAbajo = (Transportador) posicionAbajo;
                        abajo = getNumberWithCero(transportadorAbajo.getyTransportador() - 1) + getNumberWithCero(transportadorAbajo.getxTransportador() - 1);
                    } else {
                        abajo = getNumberWithCero(posicionAbajo.getY() - 1) + getNumberWithCero(posicionAbajo.getX() - 1);
                        if (posicionAbajo.getY() - 1 == -1 || posicionAbajo.getX() - 1 == -1 || posicionAbajo.getY() - 1 == escenario.getY() - 2 || posicionAbajo.getX() - 1 == escenario.getX() - 2)
                            abajo = "";
                    }

                    ElemEscenario posicionArriba = escenario.getPosicion(fila - 1, columna);
                    if (posicionArriba.isTransportable()) {
                        Transportador transportadorArriba = (Transportador) posicionArriba;
                        arriba = getNumberWithCero(transportadorArriba.getyTransportador() - 1) + getNumberWithCero(transportadorArriba.getxTransportador() - 1);
                    } else {
                        arriba = getNumberWithCero(posicionArriba.getY() - 1) + getNumberWithCero(posicionArriba.getX() - 1);
                        if (posicionArriba.getY() - 1 == -1 || posicionArriba.getX() - 1 == -1 || posicionArriba.getY() - 1 == escenario.getY() - 2 || posicionArriba.getX() - 1 == escenario.getX() - 2)
                            arriba = "";
                    }

                    Item item = elemEscenario.obtenerItem();
                    if (item != null)
                        contiene = item.tipoItem();
                }

                DataNodo entornoNodo = new DataNodo(id, getNumberWithCero(fila - 1), getNumberWithCero(columna - 1), contiene, izquierda, derecha, arriba, abajo);
                persistirNodo(entornoNodo);
            }
        }
    }
}